package com.sh.aspect;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sh.common.context.AppContextHolder;
import com.sh.common.context.RequestWrapper;
import com.sh.common.exception.BizException;
import com.sh.config.OssClientConfig;
import com.sh.enums.BizCodeEnum;
import com.sh.enums.PermissionTypeEnum;
import com.sh.pojo.dto.PermissionCacheDTO;
import com.sh.pojo.dto.ResourceTreeDTO;
import com.sh.service.permission.IUserPermissionService;
import com.sh.service.user.IUserResourceService;
import com.sh.utils.RedisKeyUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Aspect
@Component
@Slf4j
public class ResourcePermissionCheckAspect {
    private final String bucketParamKey = "bucket";
    private final String pathParamKey = "path";
    @Resource
    private IUserPermissionService userPermissionService;

    @Pointcut("execution(* com.sh.controller.UserReadResourceController.*(..))")
    public void sourceReadPermission() {
    }

    @Before("sourceReadPermission()")
    public void resourceReadPermissionCheck(JoinPoint point) throws BizException, IOException {
        Boolean isAdmin = AppContextHolder.getAdmin();
        if (isAdmin) {
            System.out.println("================ isAdmin ========================");
            return;
        }
        log.debug("start to check read permission!");

        PermissionCacheDTO permission = getPermission();
        if (permission == null || Integer.valueOf(permission.getPermission()) < Integer.valueOf(PermissionTypeEnum.READ.getCode())) {
            throw new BizException(BizCodeEnum.PERMISSION_FAIL);
        }
        return;
    }


    @Pointcut("execution(* com.sh.controller.UserWriteResourceController.*(..))")
    public void sourceWritePermission() {
    }

    @Before("sourceWritePermission()")
    public void resourceWritePermissionCheck(JoinPoint point) throws BizException, IOException {
        Boolean isAdmin = AppContextHolder.getAdmin();
        if (isAdmin) {
            System.out.println("================ isAdmin ========================");
            return;
        }
        log.info("start to check write permission!");

        PermissionCacheDTO permission = getPermission();

        if (permission == null || permission.getPermission() < PermissionTypeEnum.WRITE.getCode()) {
            throw new BizException(BizCodeEnum.PERMISSION_FAIL);
        }
        return;
    }

    private PermissionCacheDTO getPermission() throws IOException, BizException {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        // 获取请求方法类型 (GET, POST 等)
        String userId = AppContextHolder.getUserId();

        String bucket = null;
        String path = null;
        Boolean isMultiPartRequest=request.getContentType().startsWith("multipart/");
        if (isMultiPartRequest) {
            bucket = request.getParameter(bucketParamKey);
            path = request.getParameter(pathParamKey);
        } else if ("POST".equalsIgnoreCase(request.getMethod())) {
            // 将请求体解析为 Map
            Map<String, Object> bodyMap = getRequestBody(request);

            if (bodyMap != null) {
                if (bodyMap.containsKey(bucketParamKey)) {
                    bucket = (String) bodyMap.get(bucketParamKey);
                }
                if (bodyMap.containsKey(pathParamKey)) {
                    path = (String) bodyMap.get(pathParamKey);
                }
            }
        } else {
            Map<String, String[]> parameterMap = request.getParameterMap();
            bucket = parameterMap.get(bucketParamKey)[0];
            if (parameterMap.containsKey(pathParamKey)) {
                path = parameterMap.get(pathParamKey)[0];
            }
        }
        if (StringUtils.isEmpty(bucket)) {
            throw new BizException(BizCodeEnum.PARAM_ERROR);
        }

        PermissionCacheDTO permission = userPermissionService.getUserPermissionByPath(userId, bucket, path);
        return permission;
    }

    // 读取请求体的方法
    private Map<String, Object> getRequestBody(HttpServletRequest request) throws IOException {
        String bodyStr = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
        return parseRequestBody(bodyStr);
    }

    // 解析请求体 JSON 字符串为 Map
    private Map<String, Object> parseRequestBody(String body) throws IOException {
        if (body == null || body.isEmpty()) {
            return null;
        }
        // 将 JSON 字符串解析为 Map
        return new ObjectMapper().readValue(body, Map.class);
    }
}
